package cn.tpshion.config.service.impl;

import cn.tpshion.config.common.Assert;
import cn.tpshion.config.common.BusinessException;
import cn.tpshion.config.common.ErrorCode;
import cn.tpshion.config.domain.entity.ConfigInfo;
import cn.tpshion.config.domain.entity.ConfigNameInfo;
import cn.tpshion.config.service.ConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.zookeeper.data.Stat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ConfigServiceImpl implements ConfigService {

    @Autowired
    private CuratorFramework curatorFramework;

    @Override
    public List<ConfigInfo> getAllConfig() {
        List<ConfigInfo> configInfoList = new ArrayList<>();
        try {
            // 获取域配置名称
            List<String> list = curatorFramework.getChildren().forPath("/");
            for (String childPath : list) {
                // 遍历获取域配置下的配置列表
                List<String> childList = curatorFramework.getChildren().forPath("/" + childPath);
                for (String path : childList) {
                    // 获取配置内容
                    Stat stat = new Stat();
                    byte[] bytes = curatorFramework.getData().storingStatIn(stat).forPath("/" + childPath + "/" + path);
                    ConfigInfo configInfo = new ConfigInfo();
                    configInfo.setName(childPath);
                    configInfo.setKey(path);
                    configInfo.setValue(new String(bytes));
                    configInfo.setCreateTime(new Date(stat.getCtime()));
                    configInfo.setUpdateTime(new Date(stat.getMtime()));
                    configInfoList.add(configInfo);
                }
            }
        } catch (Exception e) {
            log.error("getAllConfig error：{}",e.getMessage(),e);
            throw new BusinessException(ErrorCode.FAIL.getCode(),"查询配置失败");
        }
        return configInfoList;
    }

    @Override
    public List<ConfigInfo> getConfigByName(String name) {
        List<ConfigInfo> configInfoList = new ArrayList<>();
        Assert.isTrue(checkExists(name),"配置域不存在");
        try {
            List<String> list = curatorFramework.getChildren().forPath("/" + name);
            for (String path : list) {
                // 获取配置内容
                Stat stat = new Stat();
                byte[] bytes = curatorFramework.getData().storingStatIn(stat).forPath("/" + name + "/" + path);
                ConfigInfo configInfo = new ConfigInfo();
                configInfo.setName(name);
                configInfo.setKey(path);
                configInfo.setValue(new String(bytes));
                configInfo.setCreateTime(new Date(stat.getCtime()));
                configInfo.setUpdateTime(new Date(stat.getMtime()));
                configInfoList.add(configInfo);
            }
        }catch (Exception e){
            log.error("getConfigByName error：{}",e.getMessage(),e);
            throw new BusinessException(ErrorCode.FAIL.getCode(),"查询配置失败");
        }
        return configInfoList;
    }

    @Override
    public List<ConfigInfo> getConfigByKey(String name, String key) {
        Assert.isTrue(checkExists(name),"配置域不存在");
        try {
            List<ConfigInfo> configInfoList = new ArrayList<>();
            // 查询所有子节点
            List<String> list = curatorFramework.getChildren().forPath("/" + name);
            // 遍历查询子节点数据
            for (String path : list) {
                // 获取配置内容
                Stat stat = new Stat();
                byte[] bytes = curatorFramework.getData().storingStatIn(stat).forPath("/" + name + "/" + path);
                ConfigInfo configInfo = new ConfigInfo();
                configInfo.setName(name);
                configInfo.setKey(path);
                configInfo.setValue(new String(bytes));
                configInfo.setCreateTime(new Date(stat.getCtime()));
                configInfo.setUpdateTime(new Date(stat.getMtime()));
                configInfoList.add(configInfo);
            }
            // 过滤key
            List<ConfigInfo> collect = configInfoList.stream().filter(i -> i.getKey().indexOf(key) > -1).collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(collect)){
                return collect;
            }
        }catch (Exception e){
            log.error("getConfigByName error：{}",e.getMessage(),e);
            throw new BusinessException(ErrorCode.FAIL.getCode(),"查询配置失败");
        }
        return Collections.EMPTY_LIST;
    }

    @Override
    public ConfigInfo updateConfig(String name, String key, String value) {
        Assert.isTrue(checkExists(name),"配置域不存在");
        Assert.isTrue(checkExists(name + "/" + key), key + "配置不存在");
        ConfigInfo configInfo = new ConfigInfo();
        try {
            curatorFramework.setData().forPath("/" + name + "/" + key,value.getBytes());
            Stat stat = new Stat();
            byte[] bytes = curatorFramework.getData().storingStatIn(stat).forPath("/" + name + "/" + key);
            configInfo.setName(name);
            configInfo.setKey(key);
            configInfo.setValue(new String(bytes));
            configInfo.setCreateTime(new Date(stat.getCtime()));
            configInfo.setUpdateTime(new Date(stat.getMtime()));
        }catch (Exception e){
            log.error("getConfigByName error：{}",e.getMessage(),e);
            throw new BusinessException(ErrorCode.FAIL.getCode(),"修改配置失败");
        }
        return configInfo;
    }

    @Override
    public void deleteConfig(String name, String key) {
        Assert.isTrue(checkExists(name),"配置域不存在");
        Assert.isTrue(checkExists(name + "/" + key), key + "配置不存在");
        try {
            curatorFramework.delete().forPath("/" + name + "/" + key);
        }catch (Exception e){
            log.error("getConfigByName error：{}",e.getMessage(),e);
            throw new BusinessException(ErrorCode.FAIL.getCode(),"删除配置失败");
        }
    }

    @Override
    public ConfigInfo addConfig(String name, String key, String value) {
        Assert.isTrue(checkExists(name),"配置域不存在");
        Assert.isTrue(!checkExists(name + "/" + key), key + "配置已存在");
        ConfigInfo configInfo = new ConfigInfo();
        try {
            curatorFramework.create().forPath("/" + name + "/" + key, value.getBytes());
            Stat stat = new Stat();
            byte[] bytes = curatorFramework.getData().storingStatIn(stat).forPath("/" + name + "/" + key);
            configInfo.setName(name);
            configInfo.setKey(key);
            configInfo.setValue(new String(bytes));
            configInfo.setCreateTime(new Date(stat.getCtime()));
            configInfo.setUpdateTime(new Date(stat.getMtime()));
        }catch (Exception e){
            log.error("getConfigByName error：{}",e.getMessage(),e);
            throw new BusinessException(ErrorCode.FAIL.getCode(),"添加配置失败");
        }
        return configInfo;
    }

    @Override
    public List<ConfigNameInfo> getAllConfigName() {
        List<ConfigNameInfo> list = new ArrayList<>();
        try {
            List<String> childrenPath = curatorFramework.getChildren().forPath("/");
            for (String path : childrenPath) {
                byte[] bytes = curatorFramework.getData().forPath("/" + path);
                ConfigNameInfo configNameInfo = new ConfigNameInfo();
                configNameInfo.setName(path);
                if(Objects.nonNull(bytes) && bytes.length > 0){
                    configNameInfo.setDesc(new String(bytes));
                }
                list.add(configNameInfo);
            }
        }catch (Exception e){
            log.error("getConfigByName error：{}",e.getMessage(),e);
            throw new BusinessException(ErrorCode.FAIL.getCode(),"查询配置域失败");
        }
        return list;
    }

    @Override
    public void addName(String name, String desc) {
        Assert.isTrue(!checkExists(name), name + "配置域已存在");
        try {
            if(StringUtils.hasText(desc)){
                curatorFramework.create().forPath("/" + name, desc.getBytes());
            }else{
                curatorFramework.create().forPath("/" + name);
            }
        }catch (Exception e){
            log.error("getConfigByName error：{}",e.getMessage(),e);
            throw new BusinessException(ErrorCode.FAIL.getCode(),"添加配置域失败");
        }
    }

    @Override
    public List<ConfigInfo> queryConfig(String name, String key) {
        try {
            List<ConfigInfo> configInfoList = new ArrayList<>();
            // 获取域配置名称
            List<String> list = curatorFramework.getChildren().forPath("/");
            for (String childPath : list) {
                // 遍历获取域配置下的配置列表
                List<String> childList = curatorFramework.getChildren().forPath("/" + childPath);
                for (String path : childList) {
                    // 获取配置内容
                    Stat stat = new Stat();
                    byte[] bytes = curatorFramework.getData().storingStatIn(stat).forPath("/" + childPath + "/" + path);
                    ConfigInfo configInfo = new ConfigInfo();
                    configInfo.setName(childPath);
                    configInfo.setKey(path);
                    configInfo.setValue(new String(bytes));
                    configInfo.setCreateTime(new Date(stat.getCtime()));
                    configInfo.setUpdateTime(new Date(stat.getMtime()));
                    configInfoList.add(configInfo);
                }
            }
            // name 和 key 都为空，表示查询全部
            if(!StringUtils.hasText(name) && !StringUtils.hasText(key)){
                return configInfoList;
            }
            if(!CollectionUtils.isEmpty(configInfoList)){
                if(StringUtils.hasText(name)){
                    configInfoList = configInfoList.stream().filter(i -> i.getName().equals(name)).collect(Collectors.toList());
                }
                if(StringUtils.hasText(key)){
                    configInfoList = configInfoList.stream().filter(i -> i.getKey().contains(key)).collect(Collectors.toList());
                }
                return configInfoList;
            }
        } catch (Exception e) {
            log.error("getAllConfig error：{}",e.getMessage(),e);
            throw new BusinessException(ErrorCode.FAIL.getCode(),"查询配置失败");
        }
        return Collections.emptyList();
    }

    private boolean checkExists(String name){
        Stat stat = null;
        try {
            stat = curatorFramework.checkExists().forPath("/" + name);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(Objects.isNull(stat)){
            return false;
        }
        return true;
    }
}
